import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;


public class Tuner {

	final float sampleRate = 8000;
    final int sampleSizeInBits = 8;
    final int channels = 1;
    final boolean signed = false;
    final boolean bigEndian = false;

    //final int bufferSize = 8192;
    //final int bufferSize = 16384;
    final int bufferSize = 10000;
    byte buffer[] = new byte[bufferSize];
	double real[] = new double[bufferSize];
	double imag[] = new double[bufferSize];
	double freqTable[] = new double[bufferSize];
	
	AudioFormat format;
	DataLine.Info info;
	TargetDataLine line;
	
    public Tuner() {
	    format = new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
	    info = new DataLine.Info(TargetDataLine.class, format);
	    if (!AudioSystem.isLineSupported(info)) {
            System.err.println("Line not supported");
            System.exit(0);
        }
		for (int i=0; i<bufferSize; ++i)
			freqTable[i] = (sampleRate * i)/bufferSize;
    }
    
    public void tune() {
	    try {
			line = (TargetDataLine) AudioSystem.getLine(info);
			line.open(format);
		    line.start();
			while (true) {
				int count = line.read(buffer, 0, buffer.length);
				if (count > 0) {
					for (int i = 0; i < count; i++) {
			            real[i] = buffer[i];
			            imag[i] = 0;
					}
					
					Fft.transform(real, imag);
					
					double maxFreq = 0;
					int maxInd = 0;
					double abs;
					for (int i=0; i<real.length/2; i++) {
						abs = real[i]*real[i] + imag[i]*imag[i];
						if (abs > maxFreq) {
							maxFreq = abs;
							maxInd = i;
						}
					}
					System.out.println("F=" + freqTable[maxInd] + ", " + Notes.findNote(freqTable[maxInd]));
				}
			}
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}
    }
    
    public void tune(String note) {
    	int ind = Notes.findNoteIndex(note);
	    try {
			line = (TargetDataLine) AudioSystem.getLine(info);
			line.open(format);
		    line.start();
			while (true) {
				int count = line.read(buffer, 0, buffer.length);
				if (count > 0) {
					for (int i = 0; i < count; i++) {
			            real[i] = buffer[i];
			            imag[i] = 0;
					}
					
					Fft.transform(real, imag);
					
					double maxFreq = 0;
					int maxInd = 0;
					double abs;
					for (int i=0; i<real.length/2; i++) {
						abs = real[i]*real[i] + imag[i]*imag[i];
						if (abs > maxFreq) {
							maxFreq = abs;
							maxInd = i;
						}
					}
					double d = Notes.freq[ind] - freqTable[maxInd];
					if (d >= 0)
						System.out.println(note + ", UP, d = " + Math.abs(d));
					else
						System.out.println(note + ", DOWN, d = " + Math.abs(d));
				}
			}
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		}
    }
    
    private void destroy() {
    	line.stop();
    	line.close();
    }
    
}
